package com.javen.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Javen
 */
@Configuration
@Slf4j
public class RabbitMqConfig {
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(new Jackson2JsonMessageConverter());

        // 消息是否成功发送到 Exchange
        template.setConfirmCallback((correlationData, ack, cause) -> {
            log.info("消息发送状态: correlationData: {}, ack: {}, cause: {}", correlationData, ack, cause);
            if (ack) {
                log.info("消息成功发送到 Exchange");
                // 状态: 0投递中 1投递成功 2投递失败 3已消费
            } else {
                log.error("消息发送到 Exchange 失败, {}, cause: {}", correlationData, cause);
            }
        });
        // 消息是否从 Exchange 路由到 Queue
        // 注意: 这是一个失败回调, 只有消息从 Exchange 路由到 Queue 失败才会回调这个方法
        template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) ->
                log.error("消息从 Exchange 路由到 Queue 失败: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}",
                        exchange, routingKey, replyCode, replyText, message));
        return template;
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;
    }
}